#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/kthread.h>
#include <linux/delay.h>

struct task_struct *monitor_thread;

static int monitor_fn(void *data)
{
	struct task_struct *g, *p;

    bool is_kthread;
    bool is_frozen;
    bool is_waking;
    bool is_interruptible;
    bool is_uninterruptible;
    bool is_freezable;
    int saved_state = -1;
    while(!kthread_should_stop()) {
        rcu_read_lock();
        for_each_process_thread(g, p) {
            is_kthread = p->flags & PF_KTHREAD;
            is_frozen = READ_ONCE(p->__state) & TASK_FROZEN;
            is_waking = READ_ONCE(p->__state) & TASK_WAKING;
            is_interruptible = READ_ONCE(p->__state) & TASK_INTERRUPTIBLE;
            is_uninterruptible = READ_ONCE(p->__state) & TASK_UNINTERRUPTIBLE;
            is_freezable = READ_ONCE(p->__state) & TASK_FREEZABLE;
            if(!strcmp(p->comm, "freeze_monitor_")) {
                if(saved_state != p->__state)
                    pr_info("Process %s [%d] %s state:: fozen:%d waking:%d interr:%d unin:%d freezable:%d \n",
                            p->comm, p->pid, is_kthread == 1 ? "kthread":"userthread", is_frozen, is_waking, is_interruptible, is_uninterruptible, is_freezable);

                saved_state = p->__state;
            }
        }
        rcu_read_unlock();

        schedule();
    }
    return 0;
}


static int __init freeze_monitor_init(void)
{
    pr_info("Freeze monitor module inited\n");
    monitor_thread = kthread_run(monitor_fn, NULL, "monitor_thread");
    if (IS_ERR(monitor_thread)) 
        return PTR_ERR(monitor_thread);
    return 0;
}

static void __exit freeze_monitor_exit(void)
{
     if (monitor_thread) {
        kthread_stop(monitor_thread);  
        monitor_thread = NULL;
    }
    pr_info("Freeze monitor module exited\n");
}

module_init(freeze_monitor_init);
module_exit(freeze_monitor_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("zzhwaxy");
MODULE_DESCRIPTION("Monitor process state during freeze");

